package net.chrisrichardson.ec2deployer.cluster

import net.chrisrichardson.ec2deployer.core.*

/**
Configures a cluster consisting of the following:
MySQL server
One or more Tomcat servers with one or more web applications
An Apache server that load balancers across the tomcat servers
One or more Jmeter machines
*/

class SimpleCluster {

    ClusterSpec spec
    ClusterInstance clusterInstance

    def CloudManager ec2

    protected SimpleCluster() {}

    def SimpleCluster(CloudManager ec2, ClusterSpec spec) {
        this.ec2 = ec2
        this.spec = spec
    }


    def SimpleCluster(CloudManager ec2, ClusterDefinition definition) {
        this.ec2 = ec2
        this.spec = definition.spec
        if (!definition.serverState.empty)
            this.clusterInstance = new ClusterInstance(ec2, spec, definition.serverState)
    }


    ClusterSpec getSpec() {
        spec
    }

    def getServerState() {
        clusterInstance.serverState
    }

    /**
    Start the cluster, optionally reusing existing instances
    */

    public void start(boolean reuseRunningInstances = false) {
        clusterInstance = new ClusterInstance(ec2, spec)
        clusterInstance.start(reuseRunningInstances)
    }
    
    public void allocateAndAssignHosts() {
      clusterInstance = new ClusterInstance(ec2, spec)
      clusterInstance.allocateAndAssignHosts()
    }
    
    public void startTiers() {
      clusterInstance.startTiers()
    }

    /**
      Run a Jmeter load test
   */

    def loadTest(jmxFileName, threadCounts, List<String> dataFiles) {
        clusterInstance.loadTest(jmxFileName, threadCounts, dataFiles)
    }

    /**
    Terminate all theinstances
    */

    void stop() {
        clusterInstance.stop()
    }

    /**
        Printout some information about the cluster
    */

    def dumpInfo() {
        if (clusterInstance)
            clusterInstance.dumpInfo()
    }

    def redeploy() {
        clusterInstance.redeploy()
    }
    
    def dbSave(String s3Path) {
      clusterInstance.dbSave(s3Path)
    }

    def dbRestore(String s3Path) {
      clusterInstance.dbRestore(s3Path)
    }

    def dbRecreate() {
        clusterInstance.dbRecreate()
    }

    SimpleCluster cloneCluster() {

        ec2.startPolling()
        
        ClusterSpec clonedClusterSpec = spec.makeCopyForClone()

        String webAppsTarPath = clusterInstance.snapshotWebApplications()

        List<String> originalDbScripts = clonedClusterSpec.schemaSpec.scripts

        cloneDatabase(clonedClusterSpec)

        SimpleCluster newCluster = new SimpleCluster(ec2, clonedClusterSpec)
        newCluster.allocateAndAssignHosts();

        clonedClusterSpec.webAppBundle = webAppsTarPath

        newCluster.startTiers()

        clonedClusterSpec.schemaSpec.scripts = originalDbScripts

        clonedClusterSpec.webAppBundle = null

        newCluster
    }

    void cloneDatabase(ClusterSpec clonedClusterSpec) {
        if (clonedClusterSpec.ebsVolume) {
            String snapshotId = clusterInstance.snapshotDatabase();
            clonedClusterSpec.withEbsVolumeFromSnapshot(snapshotId, null, clonedClusterSpec.ebsVolume.device)
        } else {
            def s3Path = makeS3PathForClone()
            this.dbSave(s3Path)
            clonedClusterSpec.schemaSpec.scripts = ["s3://${s3Path}"]
        }
    }

    def makeS3PathForClone() {
        "${ec2.awsProperties.accessKey}.tmp-clone-db/snapshot"
    }

    def executeSqlScripts(scripts) {
        clusterInstance.executeSqlScripts scripts
    }

    boolean isAllInstancesRunning() {
        clusterInstance.isAllInstancesRunning()
    }

    boolean isAllInstancesTerminated() {
        clusterInstance.isAllInstancesTerminated()
    }

}